﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Xml;
using System.Windows.Forms;
using System.Threading;

namespace ShadowHelper
{
    public partial class Form1 : Form
    {
        private String url = "https://gentle-oasis-59484.herokuapp.com/subscribe";
        public List<Source> Sources { set; get; }
        private SynchronizationContext m_SyncContext = null;
        private int selectedIndex;
        public delegate void CallBackDelegate(String message);
        private CallBackDelegate cbd;
        private void UpdateAccounts(String htmlStr)
        {
            if (!String.IsNullOrEmpty(htmlStr))
            {
                htmlStr = SS_SSRLinkHandler.DecodeBase64String(htmlStr);
                String[] links = htmlStr.Split('\n');
                if (links != null)
                {
                    Sources[selectedIndex].Accounts.Clear();
                    Sources[selectedIndex].Accounts.AddRange(links);
                    m_SyncContext.Post(SetCbAccount, null);//cbSource_SelectedIndexChanged(this, null);

                    XmlDocument xmlDoc = new XmlDocument();
                    xmlDoc.Load("config.xml");
                    XmlNode rootNode = xmlDoc.SelectSingleNode("Config");
                    XmlNode oldNode = xmlDoc.SelectSingleNode("/Config/source["+ selectedIndex + 1 +"]");//rootNode.ChildNodes[cbSource.SelectedIndex];
                    XmlNode newNode = xmlDoc.CreateNode(XmlNodeType.Element, "source", null);

                    foreach (XmlAttribute xa in oldNode.Attributes)
                    {
                        XmlAttribute attribute = xmlDoc.CreateAttribute(xa.Name);
                        attribute.Value = xa.Value;
                        newNode.Attributes.Append(attribute);
                    }
                    foreach (String link in links)
                    {
                        XmlNode account = xmlDoc.CreateNode(XmlNodeType.Element, "account", null);
                        account.InnerText = link;
                        newNode.AppendChild(account);
                    }

                    rootNode.ReplaceChild(newNode, oldNode);
                    rootNode.Attributes[0].Value = selectedIndex.ToString();
                    xmlDoc.Save("config.xml");
                    MessageBox.Show("Update completed!", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                else
                {
                    MessageBox.Show("Format of the downloaded content is incorrect!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            else
            {
                MessageBox.Show("Downloaded content is empty!", "Fail", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }

        private void Download(object obj)
        {
            try
            {
                // Get links
                WebRequest request = WebRequest.Create(url);
                WebResponse response = request.GetResponse();
                Stream datastream = response.GetResponseStream();
                StreamReader reader = new StreamReader(datastream, Encoding.UTF8);
                String htmlStr = reader.ReadToEnd();
                reader.Close();
                datastream.Close();
                response.Close();

                CallBackDelegate cbd = obj as CallBackDelegate;
                cbd(htmlStr);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                m_SyncContext.Post(SetBtnUpdate, "Update accounts:1");
            }
        }

        private void SetCbAccount(object obj)
        {
            cbSource_SelectedIndexChanged(this, null);
        }

        private void SetBtnUpdate(object obj)
        {
            String[] paramStr = obj.ToString().Split(':'); 
            btnUpdate.Text = paramStr[0];
            btnUpdate.Enabled = (paramStr[1] == "1" ? true : false);
        }

        public Form1()
        {
            InitializeComponent();
            Sources = new List<Source>();
            m_SyncContext = SynchronizationContext.Current;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            if (File.Exists(".\\config.xml"))
            {
                Source source = null;
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.Load(".\\config.xml");
                XmlNode rootNode = xmlDoc.SelectSingleNode("Config");
                int usedIndex = Convert.ToInt32(rootNode.Attributes["usedIndex"].Value);
                foreach (XmlNode xn in rootNode.ChildNodes)
                {
                    source = new Source
                    {
                        Id = xn.Attributes["id"].Value,
                        Name = xn.Attributes["name"].Value,
                        Url = xn.Attributes["url"].Value
                    };
                    XmlNodeList accountList = xn.ChildNodes;
                    if(accountList != null)
                    {
                        source.Accounts = new List<String>();
                        foreach (XmlNode accountNode in accountList)
                        {
                            source.Accounts.Add(accountNode.InnerText);
                        }
                    }
                    Sources.Add(source);
                }
                if(Sources.Count > 0)
                {
                    cbSource.Items.Clear();
                    foreach (Source src in Sources)
                    {
                        cbSource.Items.Add(src.Name);
                    }
                    cbSource.SelectedIndex = usedIndex;
                }
                else
                {
                    btnUpdate.Enabled = false;
                }
                
                if(Sources.Count > 0 && Sources[cbSource.SelectedIndex].Accounts != null && Sources[cbSource.SelectedIndex].Accounts.Count > 0)
                {
                    cbAccount.Items.Clear();
                    cbAccount.Items.AddRange(Sources[cbSource.SelectedIndex].Accounts.ToArray());
                    cbAccount.SelectedIndex = 0;
                }
                else
                {
                    btnOK.Enabled = false;
                }
            }
            else
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.InnerXml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Config usedIndex=\"-1\"></Config>";
                //XmlElement rootElement = xmlDoc.CreateElement("Config");
                //rootElement.SetAttribute("usedIndex", "0");
                //xmlDoc.AppendChild(rootElement);
                xmlDoc.Save("config.xml");
                btnUpdate.Enabled = false;
                btnOK.Enabled = false;
            }
            
        }
        
        private void btnUpdate_Click(object sender, EventArgs e)
        {
            btnUpdate.Enabled = false;
            btnUpdate.Text = "Updating...";
            btnUpdate.Refresh();
            cbd = UpdateAccounts;
            url = Sources[cbSource.SelectedIndex].Url;
            selectedIndex = cbSource.SelectedIndex;
            Thread downloadThread = new Thread(Download);
            downloadThread.Start(cbd);
            //try
            //{
            //    // Get links
            //    WebRequest request = WebRequest.Create(url);
            //    WebResponse response = request.GetResponse();
            //    Stream datastream = response.GetResponseStream();
            //    StreamReader reader = new StreamReader(datastream, Encoding.UTF8);
            //    String htmlStr = reader.ReadToEnd();
            //    reader.Close();
            //    datastream.Close();
            //    response.Close();
                
            //    if (!String.IsNullOrEmpty(htmlStr))
            //    {
            //        htmlStr = SS_SSRLinkHandler.DecodeBase64String(htmlStr);
            //        String[] links = htmlStr.Split('\n');
            //        if (links != null)
            //        {
            //            Sources[cbSource.SelectedIndex].Accounts.Clear();
            //            Sources[cbSource.SelectedIndex].Accounts.AddRange(links);
            //            cbSource_SelectedIndexChanged(this, null);

            //            XmlDocument xmlDoc = new XmlDocument();
            //            xmlDoc.Load("config.xml");
            //            XmlNode rootNode =  xmlDoc.SelectSingleNode("Config");
            //            XmlNode oldNode = rootNode.SelectSingleNode("//source[@url='"+ url +"']");//SelectSingleNode("/Config/source["+ cbSource.SelectedIndex + 1 +"]");//rootNode.ChildNodes[cbSource.SelectedIndex];
            //            XmlNode newNode = xmlDoc.CreateNode(XmlNodeType.Element, "source", null);

            //            foreach (XmlAttribute xa in oldNode.Attributes)
            //            {
            //                XmlAttribute attribute = xmlDoc.CreateAttribute(xa.Name);
            //                attribute.Value = xa.Value;
            //                newNode.Attributes.Append(attribute);
            //            }
            //            foreach (String link in links)
            //            {
            //                XmlNode account = xmlDoc.CreateNode(XmlNodeType.Element, "account", null);
            //                account.InnerText = link;
            //                newNode.AppendChild(account);
            //            }

            //            rootNode.ReplaceChild(newNode, oldNode);
            //            rootNode.Attributes[0].Value = cbSource.SelectedIndex.ToString();
            //            xmlDoc.Save("config.xml");
            //            MessageBox.Show("Update succeeds");
            //        }
            //        else
            //        {
            //            MessageBox.Show("Format of the downloaded content is incorrect");
            //        }
            //    }
            //    else
            //    {
            //        MessageBox.Show("Downloaded content is empty!");
            //    }
            //}
            //catch (Exception ex)
            //{
            //    MessageBox.Show(ex.Message);
            //}
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            if (tbFile.Text != "")
            {
                try
                {
                    // Get SS/SSR link
                    SS_SSRLinkHandler handler = new SS_SSRLinkHandler
                    {
                        Link = cbAccount.SelectedItem.ToString()
                    };
                    Console.WriteLine("URL: {0}", handler.Link);
                    Dictionary<String, String> paramDic = handler.GetParams();

                    Setting.DoSetting(tbFile.Text, paramDic);

                    // Set usedIndex to xml
                    XmlDocument xmlDoc = new XmlDocument();
                    xmlDoc.Load("config.xml");
                    XmlNode rootNode = xmlDoc.SelectSingleNode("Config");
                    rootNode.Attributes[0].Value = cbSource.SelectedIndex.ToString();
                    xmlDoc.Save("config.xml");
                    MessageBox.Show("Done!!!", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            else
            {
                MessageBox.Show("Please enter the file path of the SS/SSR exe file!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void btnSetFile_Click(object sender, EventArgs e)
        {
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                tbFile.Text = openFileDialog.FileName;
            }
        }

        private void btnSetSource_Click(object sender, EventArgs e)
        {
            SourceForm sourceForm = new SourceForm();
            sourceForm.ShowDialog(this);
        }

        public void cbSource_SelectedIndexChanged(object sender, EventArgs e)
        {
            cbAccount.Items.Clear();
            List<String> accounts = Sources[cbSource.SelectedIndex].Accounts;
            if (accounts.Count > 0)
            {
                cbAccount.Items.AddRange(accounts.ToArray());
                btnOK.Enabled = true;
                cbAccount.SelectedIndex = 0;
            }
            else
            {
                cbAccount.Text = "None";
                btnOK.Enabled = false;
            }
        }

    }
}
